package utils

import (
	"context"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"

	"github.com/schollz/progressbar/v3"
)

// HttpDo 发送HTTP请求并返回响应体
// url: 请求地址
// method: HTTP方法（如GET、POST等）
// data: 请求体数据，可以为nil
// header: 请求头信息，键值对形式
// 返回值:
// []byte: 响应体内容
// error: 错误信息，如果请求失败或状态码非200则返回错误
func HttpDo(ctx context.Context, url, method string, data io.Reader, header map[string]interface{}) ([]byte, error) {
	req, err := http.NewRequest(method, url, data)
	if err != nil {
		return nil, err
	}
	// 设置请求头
	for k, v := range header {
		req.Header.Set(k, v.(string))
	}
	client := http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}

	defer resp.Body.Close()

	respBody, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	// 检查HTTP状态码是否为200
	if resp.StatusCode != http.StatusOK {
		log.Printf("失败body: %v", string(respBody))
		return nil, fmt.Errorf("下载失败，HTTP状态码: %d", resp.StatusCode)
	}

	return respBody, nil
}

// DownloadFile 下载文件并保存到指定路径，同时显示进度条
// url: 下载链接
// method: HTTP方法（如GET、POST等）
// dest: 文件保存路径
// data: 请求体数据，可以为nil
// header: 请求头信息，键值对形式
// 返回值:
// int64: 下载文件的大小（字节）
// *[]byte: 响应体内容的指针（当前未实际使用，始终为空）
// error: 错误信息，如果下载失败则返回错误
func DownloadFile(ctx context.Context, url, method, dest string, data io.Reader, header map[string]interface{}) (int64, *[]byte, error) {
	log.Println("开始下载数据...")
	req, err := http.NewRequest(method, url, data)
	if err != nil {
		return 0, nil, err
	}
	// 设置请求头
	for k, v := range header {
		req.Header.Set(k, v.(string))
	}
	client := http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return 0, nil, err
	}
	// 检查HTTP状态码是否为200
	if resp.StatusCode != http.StatusOK {
		return 0, nil, fmt.Errorf("下载失败，HTTP状态码: %d", resp.StatusCode)
	}
	defer resp.Body.Close()

	var respBody []byte
	var readErr error

	f, _ := os.OpenFile(dest, os.O_CREATE|os.O_WRONLY, 0644)
	defer f.Close()

	// 创建进度条并开始下载
	bar := progressbar.DefaultBytes(
		resp.ContentLength,
		"downloading",
	)
	_, err = io.Copy(io.MultiWriter(f, bar), resp.Body)
	if err != nil {
		return 0, nil, err
	}

	if readErr != nil {
		return 0, nil, readErr
	}
	log.Println("下载完成")

	return resp.ContentLength, &respBody, nil
}
